﻿using System;
using System.Threading;

namespace Isuka.Auxiliaries
{
    public abstract class DisposableObject
        : IDisposable
    {
        /// <summary>
        /// リソースが解放されているかどうかを示します。
        /// </summary>
        int disposed = 0;

        ~DisposableObject()
        {
            Dispose(false);
        }

        protected virtual bool IsDisposed
        {
            get { return disposed != 0; }
        }

        /// <summary>
        /// オブジェクトが破棄されている場合エラー
        /// </summary>
        protected void VerifyNotDisposed()
        {
            if (IsDisposed)
            {
                throw new ObjectDisposedException(GetType().FullName);
            }
        }

        /// <summary>
        /// DisposableObject で使用されるすべてのリソースを解放します。
        /// 一度に呼ばれる Dispose は一回だけです。
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// DisposableObject によって使用されているアンマネージ リソースを解放し、
        /// オプションでマネージ リソースも解放します。
        /// </summary>
        /// <param name="disposing">
        /// マネージ リソースとアンマネージ リソースの両方を解放する場合は true。
        /// アンマネージ リソースだけを解放する場合は false。
        /// </param>
        void Dispose(bool disposing)
        {
            if (Interlocked.Exchange(ref disposed, 1) == 0)
            {
                if (disposing)
                {
                    // TODO: マネージ リソースを解放
                    DisposeManagedResource();
                }
                // TODO: アンマネージ リソースを解放
                DisposeUnmanagedResource();
            }
        }

        protected virtual void DisposeManagedResource() { }

        protected virtual void DisposeUnmanagedResource() { }


    }
}
